package cn.yeziji.netty.adapter;

import cn.yeziji.forum.basic.netty.Message;
import cn.yeziji.forum.common.key.ChatroomCacheKey;
import cn.yeziji.forum.common.key.DetailsCacheKey;
import cn.yeziji.forum.common.key.NoticeCacheKey;
import cn.yeziji.forum.utils.RedisUtils;
import cn.yeziji.forum.utils.SpringUtils;
import cn.yeziji.netty.config.handler.NettyWebsocketHandler;
import cn.yzj.common.CommonSymbol;
import com.alibaba.fastjson.JSON;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 选定类型
 *
 * @author gzkemays
 * @since 2022/11/08 10:43 AM
 */
public abstract class SelectedTypes<T> {
  /**
   * 选择参数类型
   *
   * <p>{@link }
   *
   * <pre>
   *    -2: 用户退出登录
   *    -1: 用户登录
   *     0: 用户进入公共聊天室
   *     1: 用户进入私聊聊天室
   *     2: 用户退出私聊聊天室
   *     3: 用户退出公共聊天室
   *     4: 用户发布文章通知粉丝
   * </pre>
   */
  Integer type;

  /** 传入的 text 数据，一般为 JsonString */
  String text;

  /** 交由子类去自定义的公用 data */
  T data;

  RedisUtils redisUtils = new RedisUtils(getRedisTemplate());

  public SelectedTypes(Integer type, String text, Class<T> clazz) {
    this.type = type;
    this.text = text;
    if (text != null) {
      this.data = JSON.parseObject(text, clazz);
    }
  }

  protected void writeAndFlushMessage(
      ChannelHandlerContext channelHandlerContext, Message message) {
    // 传输消息时排除 targets 字段
    //    PropertyPreFilters.MySimplePropertyPreFilter exclude = new
    // PropertyPreFilters().addFilter();
    //    exclude.addExcludes("targets");
    if (message.getTime() != null && StringUtils.isBlank(message.getNoticeTime())) {
      // 如果生成数据时间不为空，但是通知时间为空时，构造时间差
      message.buildNoticeTime(new Date());
    }
    channelHandlerContext.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
  }

  protected void writeAndFlushMessage(
      ChannelHandlerContext channelHandlerContext, List<Message> messages) {
    // 传输消息时排除 targets 字段
    //    PropertyPreFilters.MySimplePropertyPreFilter exclude = new
    // PropertyPreFilters().addFilter();
    //    exclude.addExcludes("targets");
    // 构造时间
    List<Message> collect =
        messages.stream()
            .peek(
                message -> {
                  if (message.getTime() != null && StringUtils.isBlank(message.getNoticeTime())) {
                    // 如果生成数据时间不为空，但是通知时间为空时，构造时间差
                    message.buildNoticeTime(new Date());
                  }
                })
            .collect(Collectors.toList());
    channelHandlerContext.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(collect)));
  }

  protected void writeAndFlush(ChannelHandlerContext channelHandlerContext, Object object) {
    channelHandlerContext.writeAndFlush(
        new TextWebSocketFrame(
            JSON.toJSONString(new Message(this.type, JSON.toJSONString(object)))));
  }

  /** 已读信息 */
  protected void readMessage(String noticeUser, List<Message> msgList) {
    if (!msgList.isEmpty()) {
      // 添加至已读
      redisUtils.listFooterPushAll(NoticeCacheKey.READ + noticeUser, msgList);
      // 移出未读
      for (Message msg : msgList) {
        redisUtils.listFooterRemove(NoticeCacheKey.UN_READ + noticeUser, msg);
      }
    }
  }

  /**
   * 获取离线聊天记录的缓存键值
   *
   * @param nickname 用户昵称
   * @return 键值
   */
  protected String getChatLeaveCacheKey(String nickname) {
    return ChatroomCacheKey.LEAVE_PRIVATE_CHAT_KEY + nickname;
  }

  /**
   * 获取在线聊天室的缓存键值
   *
   * @param nickname 用户昵称
   * @return 键值
   */
  protected String getChatOnlineCacheKey(String nickname) {
    return ChatroomCacheKey.ONLINE_PRIVATE_CHAT_KEY + CommonSymbol.STAR_SIGN + "&" + nickname;
  }

  /**
   * 文章通知缓存键值
   *
   * @param nickname 通知的用户名
   * @return 键值
   */
  protected String getDetailNoticeCacheKey(String nickname) {
    return DetailsCacheKey.PUBLISH_NOTICE_KEY + nickname;
  }

  /** 从 IOC 控制器中获取 netty websocket handler */
  protected NettyWebsocketHandler getNettyWebsocketHandler() {
    return SpringUtils.getBean(NettyWebsocketHandler.class);
  }
  /** 从 IOC 控制器中获取 redisTemplate */
  protected RedisTemplate<String, Object> getRedisTemplate() {
    return SpringUtils.getBean("redisTemplate");
  }

  /** 从 IOC 控制器中获取 rabbitTemplate */
  protected RabbitTemplate getRabbitTemplate() {
    return SpringUtils.getBean(RabbitTemplate.class);
  }
}
